package blockchain

import (
	"aqchain/pkg/blockchain/contract/sale"
	"aqchain/pkg/log"
	"aqchain/pkg/model"
	"context"
	"gitee.com/aqchain/go-ethereum/accounts/abi/bind"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

func (c *Client) SubscribeSaleContractEvent(ctx context.Context) error {
	createChan := make(chan *sale.SaleContractCreate)
	cancelChan := make(chan *sale.SaleContractCancel)
	confirmChan := make(chan *sale.SaleContractConfirm)
	createSub, err := c.saleContract.WatchCreate(&bind.WatchOpts{Context: ctx}, createChan, nil)
	if err != nil {
		return err
	}
	defer createSub.Unsubscribe()
	cancelSub, err := c.saleContract.WatchCancel(&bind.WatchOpts{Context: ctx}, cancelChan, nil)
	if err != nil {
		return err
	}
	defer cancelSub.Unsubscribe()
	confirmSub, err := c.saleContract.WatchConfirm(&bind.WatchOpts{Context: ctx}, confirmChan, nil)
	if err != nil {
		return err
	}
	defer confirmSub.Unsubscribe()

	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case err = <-createSub.Err():
			return err
		case err = <-cancelSub.Err():
			return err
		case err = <-confirmSub.Err():
			return err
		case event := <-createChan:
			err = c.handleCreateSale(event)
			if err != nil {
				return err
			}
		case event := <-cancelChan:
			err = c.handleCancelSale(event)
			if err != nil {
				return err
			}
		case event := <-confirmChan:
			err = c.handleConfirmSale(event)
			if err != nil {
				return err
			}
		}
	}
}

func (c *Client) handleCreateSale(event *sale.SaleContractCreate) error {
	block, err := c.client.BlockByHash(context.Background(), event.Raw.BlockHash)
	if err != nil {
		return err
	}
	// 根据DCI获取Item
	var itemRecord model.Item
	err = c.db.Where(&model.Item{DCI: event.Dci}).First(&itemRecord).Error
	if err != nil {
		return err
	}
	err = c.db.Transaction(func(tx *gorm.DB) error {
		// 保存Sale
		newSale := model.Sale{
			DCI:       event.Dci,
			Seller:    event.Seller.String(),
			Buyer:     event.Buyer.String(),
			Price:     event.Price.String(),
			BlockTime: block.Time().Uint64(),
		}
		err = tx.Create(&newSale).Error
		if err != nil {
			return err
		}
		// 创建SaleEvent
		newEvent := model.SaleEvent{
			TxHash:      event.Raw.TxHash.String(),
			DCI:         event.Dci,
			From:        event.Seller.String(),
			Value:       event.Price.String(),
			EventName:   "create",
			BlockNumber: event.Raw.BlockNumber,
			BlockTime:   block.Time().Uint64(),
		}
		err = tx.Create(&newEvent).Error
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	log.Logger.Debug("接收到定价交易创建事件", zap.String("DCI", event.Dci), zap.String("Seller", event.Seller.String()), zap.String("Buyer", event.Buyer.String()), zap.Uint64("Value", event.Price.Uint64()))
	return nil
}

func (c *Client) handleCancelSale(event *sale.SaleContractCancel) error {
	block, err := c.client.BlockByHash(context.Background(), event.Raw.BlockHash)
	if err != nil {
		return err
	}
	// 根据DCI获取Item
	var itemRecord model.Item
	err = c.db.Where(&model.Item{DCI: event.Dci}).First(&itemRecord).Error
	if err != nil {
		return err
	}
	err = c.db.Transaction(func(tx *gorm.DB) error {
		// 删除Sale
		err = tx.Delete(&model.Sale{DCI: event.Dci}).Error
		if err != nil {
			return err
		}
		// 创建新的交易记录
		newEvent := model.SaleEvent{
			TxHash:      event.Raw.TxHash.String(),
			DCI:         event.Dci,
			From:        event.Seller.String(),
			EventName:   "cancel",
			BlockNumber: event.Raw.BlockNumber,
			BlockTime:   block.Time().Uint64(),
		}
		err = tx.Create(&newEvent).Error
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	log.Logger.Debug("接收到定价交易取消事件", zap.String("DCI", event.Dci), zap.String("Seller", event.Seller.String()), zap.String("Buyer", event.Buyer.String()), zap.Uint64("Value", event.Price.Uint64()))
	return nil
}

func (c *Client) handleConfirmSale(event *sale.SaleContractConfirm) error {
	block, err := c.client.BlockByHash(context.Background(), event.Raw.BlockHash)
	if err != nil {
		return err
	}
	var itemRecord model.Item
	err = c.db.Where(&model.Item{DCI: event.Dci}).First(&itemRecord).Error
	if err != nil {
		return err
	}
	err = c.db.Transaction(func(tx *gorm.DB) error {
		err = c.db.Delete(&model.Sale{DCI: event.Dci}).Error
		if err != nil {
			return err
		}
		newEvent := model.SaleEvent{
			TxHash:      event.Raw.TxHash.String(),
			From:        event.Buyer.String(),
			Value:       event.Price.String(),
			EventName:   "confirm",
			BlockNumber: event.Raw.BlockNumber,
			BlockTime:   block.Time().Uint64(),
		}
		err = c.db.Create(&newEvent).Error
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	log.Logger.Debug("接收到定价交易确认事件", zap.String("DCI", event.Dci), zap.String("Seller", event.Seller.String()), zap.String("Buyer", event.Buyer.String()), zap.Uint64("Value", event.Price.Uint64()))
	return nil
}
